package com.atguigu.tingshu.album.service.impl;

import com.atguigu.tingshu.album.config.VodConstantProperties;
import com.atguigu.tingshu.album.mapper.AlbumInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackInfoMapper;
import com.atguigu.tingshu.album.mapper.TrackStatMapper;
import com.atguigu.tingshu.album.service.TrackInfoService;
import com.atguigu.tingshu.album.service.VodService;
import com.atguigu.tingshu.common.constant.SystemConstant;
import com.atguigu.tingshu.common.result.Result;
import com.atguigu.tingshu.common.util.UploadFileUtil;
import com.atguigu.tingshu.model.album.AlbumInfo;
import com.atguigu.tingshu.model.album.TrackInfo;
import com.atguigu.tingshu.model.album.TrackStat;
import com.atguigu.tingshu.query.album.TrackInfoQuery;
import com.atguigu.tingshu.user.client.UserInfoFeignClient;
import com.atguigu.tingshu.vo.album.*;
import com.atguigu.tingshu.vo.user.UserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
@SuppressWarnings({"all"})
public class TrackInfoServiceImpl extends ServiceImpl<TrackInfoMapper, TrackInfo> implements TrackInfoService {

	@Autowired
	private TrackInfoMapper trackInfoMapper;

	@Autowired
	private VodConstantProperties vodConstantProperties;

    @Autowired
    private AlbumInfoMapper albumInfoMapper;

	@Autowired
	private VodService vodService;

	@Autowired
	private TrackStatMapper trackStatMapper;

	@Autowired
	private UserInfoFeignClient userInfoFeignClient;


	@Override
	public Map<String, Object> uploadTrack(MultipartFile file) {
		//	初始化客户端对象
		VodUploadClient client = new VodUploadClient(vodConstantProperties.getSecretId(), vodConstantProperties.getSecretKey());
		//	构建上传请求
		VodUploadRequest request = new VodUploadRequest();
		//	获取本地上传路径
		String tempPath = UploadFileUtil.uploadTempPath(vodConstantProperties.getTempPath(), file);
		request.setMediaFilePath(tempPath);
		//	调用上传请求：
		try {
			VodUploadResponse response = client.upload(vodConstantProperties.getRegion(), request);
			log.info("Upload FileId = {}", response.getFileId());
			//	创建一个map 对象
			Map<String, Object> map = new HashMap<>();
			//	设置mediaFileId	媒体文件的唯一标识
			map.put("mediaFileId", response.getFileId());
			//	设置mediaUrl	媒体播放地址
			map.put("mediaUrl", response.getMediaUrl());
			//	返回数据
			return map;
		} catch (Exception e) {
			// 业务方进行异常处理
			log.error("Upload Err", e);
		}
		return null;
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void saveTrackInfo(TrackInfoVo trackInfoVo, Long userId){
		/*
		 * track_info
		 * track_stat
		 * album_info
		 */

		//track_info声音信息表
		//创建对象
		TrackInfo trackInfo = new TrackInfo();
		//属性赋值
		BeanUtils.copyProperties(trackInfoVo, trackInfo);
		//获取用户Id
		trackInfo.setUserId(userId);
		//  order_num 声音在专辑中的排序值，从1开始依次递增，值越小排序越前
		/*第一种方式：查询声音表中同一张专辑的最大order_num;
		第二种：专辑包含声音总数include_track_count + 1;*/
		//初始化声音在专辑中的排序值为0
		int orderNum =0 ;

		//查询专辑中声音总数， 1.查询专辑对象
		//根据专辑id查询专辑对象
		//album_info 专辑信息表
		AlbumInfo albumInfo = albumInfoMapper.selectById(trackInfoVo.getAlbumId());
		//判断专辑对象是否为空不为空专辑总数+1
		if (null != albumInfo) {
			//include_track_count专辑包含声音总集数
			orderNum=albumInfo.getIncludeTrackCount()+1;
		}
		//设置声音在专辑中的排序值
		trackInfo.setOrderNum(orderNum);
		//调用云点播的Api获取流媒体数据
		//获取media_file_id	媒体文件的唯一标识
		TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(trackInfoVo.getMediaFileId());
		//设置media_duration 声音媒体时长，单位秒
		trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
		//设置media_type 声音媒体类型
		trackInfo.setMediaType(trackMediaInfoVo.getType());
		//设置media_url	媒体播放地址
		trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
		//设置media_size 音频文件大小，单位字节
		trackInfo.setMediaSize(trackMediaInfoVo.getSize());
		//保存数据
		trackInfoMapper.insert(trackInfo);

		//track_stat 声音统计表
		//stat_type 统计类型：0701-播放量 0702-收藏量 0703-点赞量 0704-评论数
		//播放量
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PLAY);
		//收藏量
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COLLECT);
		//点赞量
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_PRAISE);
		//评论数
		this.saveTrackStat(trackInfo.getId(), SystemConstant.TRACK_STAT_COMMENT);

		//album_info 专辑信息表
		//设置include_track_count专辑包含声音总集数+1
		albumInfo.setIncludeTrackCount(albumInfo.getEstimatedTrackCount()+1);
		//更新数据
		this.albumInfoMapper.updateById(albumInfo);
	}
	@Transactional(rollbackFor = Exception.class)
	private void saveTrackStat(Long trackId, String trackType) {
		//创建对象
		TrackStat trackStat = new TrackStat();
		//设置声音Id
		trackStat.setTrackId(trackId);
		//设置统计类型
		trackStat.setStatType(trackType);
		//设置一个100以内的随机int类型整数作为统计数目
		trackStat.setStatNum(new Random().nextInt(100));
		//保存数据
		trackStatMapper.insert(trackStat);
	}

	@Override
	public IPage<TrackListVo> findUserTrackPage(Page<TrackListVo> voPage, TrackInfoQuery trackInfoQuery) {
		return trackInfoMapper.selectUserTrackPage(voPage, trackInfoQuery);
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void removeTrackInfoById(Long trackId) {
		/*album_info
		* track_info
		* track_stat
		*/
		//album_info 专辑信息表
		//根据声音ID获取专辑对象
		TrackInfo trackInfo=this.getById(trackId);
		AlbumInfo albumInfo=this.albumInfoMapper.selectById(trackInfo.getAlbumId());
		//判断专辑对象是否为空
		if (null != albumInfo) {
			//将表中专辑包含声音总集数字段include_track_count-1
			albumInfo.setIncludeTrackCount(albumInfo.getIncludeTrackCount()-1);
		}
		//更新数据
		albumInfoMapper.updateById(albumInfo);
		//进行逻辑删除
		//track_info声音信息表
		trackInfoMapper.deleteById(trackId);
		//track_stat声音统计表
		trackStatMapper.delete(new LambdaQueryWrapper<TrackStat>().eq(TrackStat::getTrackId,trackId));
		//删除云点播中数据
		vodService.removeMedia(trackInfo.getMediaFileId());

		trackInfoMapper.updateOrderNum(trackInfo.getAlbumId(),trackInfo.getOrderNum());

	}

	@Override
	public void updateTrackInfoById(Long trackId, TrackInfoVo trackInfoVo) {
		/*track_info*/
		//获取声音Id获取声音对象
		TrackInfo trackInfo=this.getById(trackId);
		//获取数据库原有媒体文件唯一标识
		String originMediaFileId = trackInfo.getMediaFileId();
		//获取前端传来的媒体文件唯一标识
		String mediaFileId = trackInfoVo.getMediaFileId();
		//将前端传来的媒体文件唯一标识赋值给声音对象
		BeanUtils.copyProperties(trackInfoVo,trackInfo);
		//将原有的媒体文件唯一标识和现在的媒体文件唯一标识进行比较
		if (!originMediaFileId.equals(mediaFileId)) {
			//如果不相等就是将声音修改了，这时会将声音的信息修改
			//调用云点播的Api获取流媒体数据
			//获取media_file_id	媒体文件的唯一标识
			TrackMediaInfoVo trackMediaInfoVo = vodService.getMediaInfo(mediaFileId);
			//设置media_duration 声音媒体时长，单位秒
			trackInfo.setMediaDuration(trackMediaInfoVo.getDuration());
			//设置media_type 声音媒体类型
			trackInfo.setMediaType(trackMediaInfoVo.getType());
			//设置media_url	媒体播放地址
			trackInfo.setMediaUrl(trackMediaInfoVo.getMediaUrl());
			//设置media_size 音频文件大小，单位字节
			trackInfo.setMediaSize(trackMediaInfoVo.getSize());
			//删除vod中声音
			vodService.removeMedia(originMediaFileId);
		}
		//设置声音ID
		trackInfo.setId(trackId);
		//保存数据
		trackInfoMapper.updateById(trackInfo);
	}

	@Override
	public IPage<AlbumTrackListVo> findAlbumTrackPage(Page<AlbumTrackListVo> albumTrackListVoPage, Long albumId, Long userId) {
		//获取到专辑对应声音Id集合
		IPage<AlbumTrackListVo> albumTrackListPage =trackInfoMapper.selectAlbumTrackPage(albumTrackListVoPage,albumId);
		//获取到专辑对象
		AlbumInfo albumInfo = this.albumInfoMapper.selectById(albumId);
		//判断用户Id是否为空
		if (null != userId) {
			//这时用户未登录  需判断专辑免费还是付费问题无许考虑vip免费
			//判断专辑的类型  免费 VIP免费 以及付费
			if (!SystemConstant.ALBUM_PAY_TYPE_FREE.equals(albumInfo.getPayType())) {
				//若不为免费需将isShowPaidMark属性设置为true标记为付费 除了试听之外其余均为付费
				//获取到免费试听集数
				Integer tracksForFree = albumInfo.getTracksForFree();
				//根据声音排序值大于试听集数的声音，就是需要付费的声音  order_num > tracksForFree
				//将需要付费的声音isShowPaidMark属性设置为true
				albumTrackListPage.getRecords().stream().filter(track -> track.getOrderNum() > tracksForFree).forEach(track -> track.setIsShowPaidMark(true));

			}
		}else {
			//  声明一个变量来标识是否需要付费.
			boolean isPaid = false;
			//这时用户登录 需要考虑到用户的身份以及购买过某专辑或某集声音
			//判断专辑是否为vip免费
			if (SystemConstant.ALBUM_PAY_TYPE_VIPFREE.equals(albumInfo.getPayType())){
				//免费
				//若用户不是vip或者vip已经过期都需要付费
				Result<UserInfoVo> userInfoVoResult = this.userInfoFeignClient.getUserInfoVo(userId);
				Assert.notNull(userInfoVoResult.getData(),"用户信息为空");
				//获取用户信息
				UserInfoVo userInfoVo = userInfoVoResult.getData();
				//判断用户是否为vip
				if (userInfoVo.getIsVip() == 0 || (userInfoVo.getIsVip() == 1 && userInfoVo.getVipExpireTime().before(new Date()))){
					isPaid = true;
				}
			}else if (SystemConstant.ALBUM_PAY_TYPE_REQUIRE.equals(albumInfo.getPayType())) {
				//  付费
				isPaid = true;
			}
			//付费情况
			if(isPaid){
				//获取到需要付费的声音列表；除去试听的声音
				List<AlbumTrackListVo> albumTrackNeedPaidListVoList = albumTrackListPage.getRecords().stream().filter(track -> track.getOrderNum() > albumInfo.getTracksForFree()).collect(Collectors.toList());
				//获取到需要付费的声音Id列表
				List<Long> trackIdList = albumTrackNeedPaidListVoList.stream().map(track -> track.getTrackId()).collect(Collectors.toList());
				//远程调用判断用户是否购买过声音或专辑
				Result<Map<Long, Integer>> mapResult = this.userInfoFeignClient.userIsPaidTrack(albumId, trackIdList);
				Assert.notNull(mapResult, "远程调用失败！");
				Map<Long, Integer> map = mapResult.getData();
				Assert.notNull(map, "远程调用失败！");
				//循环遍历
				albumTrackNeedPaidListVoList.forEach(albumTrackListVo -> {
					//判断用户是否购买过声音或专辑
					/*if (map.get(albumTrackListVo.getTrackId()) == 0) {
						//若用户没有购买过声音或专辑
						albumTrackListVo.setIsShowPaidMark(true);
					}else {
						albumTrackListVo.setIsShowPaidMark(false);
					}*/
					albumTrackListVo.setIsShowPaidMark(map.get(albumTrackListVo.getTrackId()) == 0 ? true : false);

				});
			}
		}
		//返回数据
		return albumTrackListPage;
	}
	@Override
	public void trackStatUpdate(TrackStatMqVo trackStatMqVo) {
		//  本质就是执行更新操作.
		trackInfoMapper.updateTrackStatNum(trackStatMqVo.getTrackId(),trackStatMqVo.getCount(),trackStatMqVo.getStatType());
		if (trackStatMqVo.getStatType().equals(SystemConstant.TRACK_STAT_PLAY)){
			//  更新专辑:
			albumInfoMapper.updateAlbumStatNum(trackStatMqVo.getAlbumId(),trackStatMqVo.getCount(),SystemConstant.ALBUM_STAT_PLAY);
		}
	}
}
